﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Runtime = Microsoft.SqlServer.Dts.Runtime;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using SSISFromCode.Events;
using System.Diagnostics;

namespace SSISFromCode
{

    /// <summary>
    /// If actually making use of this project, this is the public guy who would have an interface or whatever.
    /// </summary>
    public class ImportDirector
    {

        private Runtime.Application _app;
        private SqlConnection _connection;
        private ImportOptions _importOptions;
        private PackageGenerator _packageGenerator;
        private ImportMessages _importMessages;

        /// <summary>
        /// Messages generated by SSIS runtime.  Messages may be generated whether or not the package is actually executed (execute param of ProcessImport()).
        /// </summary>
        public List<string> GeneratedMessages
        {
            get
            {
                return _importMessages.Messages;
            }
        }

        /// <summary>
        /// During ProcessImport, a global temp table is created in the target database.  Here is it's name.
        /// See also ReleaseGeneratedTable().
        /// </summary>
        public string GeneratedTableName
        {
            get
            {
                return _packageGenerator == null ? string.Empty : _packageGenerator.TableName;
            }
        }

        /// <summary>
        /// It is assumed that all cols in the database table that is created will be varchar, so all we would need is a list of column names.
        /// The width of the columns may vary.  See TransformationGeneratorHelper.ColumnWidth.
        /// </summary>
        public List<string> GeneratedColumns
        {
            get
            {
                return _packageGenerator == null ? null : _packageGenerator.Columns;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="EF_ConnectionStr">Connection string from entity framework.  See comments for the connection string param in ProcessImport</param>
        /// <param name="importOptions"></param>
        public ImportDirector( string EF_ConnectionStr, ImportOptions importOptions )
        {
            _app = new Runtime.Application();
            _connection = new SqlConnection( EF_ConnectionStr );
            _importOptions = importOptions;
            _importMessages = new ImportMessages();
        }

        /// <summary>
        /// Options object will be passed in in future
        /// </summary>
        /// <param name="ISConnectionStr">Tried using the connection string embedded in EF, but I couldn't get it to work</param>
        /// <param name="execute">Currently, if this is false, it saves the created package to a hard coded location</param>
        public void ProcessImport( string ISConnectionStr, bool execute = true )
        {
            _connection.Open();

            var package = CreatePackage( ISConnectionStr );

            if ( execute )
            {
                if ( package.Execute( null, null, new PackageEvents(_importMessages), null, null ) == Runtime.DTSExecResult.Failure )
                {
                    Console.WriteLine( "PACKAGE FAILED!" );
                }
            }
            else
            {
                Save( package );
            }

            if ( _packageGenerator is IRequireCleanup )
            {
                ( (IRequireCleanup)_packageGenerator ).Cleanup();
            }
        }

        private void Save( Runtime.Package package )
        {
            Debug.Assert( false, "Change path in ImportDirector.Save before attempting to save a package" );
            var path = @"C:\fakepath\fromCode.dtsx";
            var packageContents = string.Empty;
            package.SaveToXML( out packageContents, new PackageEvents(_importMessages) as Runtime.IDTSEvents );
            File.WriteAllText( path, packageContents );
        }

        /// <summary>
        /// This will become an event or something.
        /// As long as this connection is open, the global temp table created by the TableCreator class will stick around.
        /// </summary>
        public void ReleaseGeneratedTable()
        {
            _connection.Close();
        }

        private Runtime.Package CreatePackage( string ISConnectionStr )
        {
            // can't case on type
            if ( _importOptions is FixedWidthImportOptions )
            {
                _packageGenerator = new FixedWidthGenerator();
            }
            else if ( _importOptions is ExcelImportOptions )
            {
                _packageGenerator = new ExcelGenerator();
            }
            else if ( _importOptions is XMLImportOptions )
            {
                _packageGenerator = new XMLGenerator();
            }
            else
            {
                _packageGenerator = new DelimitedGenerator();
            }

            _packageGenerator.Messages = _importMessages;
            var result = _packageGenerator.Generate( _app, _importOptions, ISConnectionStr, _connection );
            return result;
        }

    }

}
